<Project>
  <PropertyGroup>
    <AndroidGenerateAppBundle Condition="'$(AndroidGenerateAppBundle)' == '' and '$(GenerateAppBundle)' != ''">$(GenerateAppBundle)</AndroidGenerateAppBundle>
    <AndroidGenerateAppBundle Condition="'$(AndroidGenerateAppBundle)' == ''">true</AndroidGenerateAppBundle>
    <AndroidGenerateAppBundle Condition="'$(_IsLibraryMode)' == 'true' and '$(ForceLibraryModeGenerateAppBundle)' != 'true'">false</AndroidGenerateAppBundle>

    <EnableDefaultAssembliesToBundle Condition="'$(EnableDefaultAssembliesToBundle)' == ''">false</EnableDefaultAssembliesToBundle>
  </PropertyGroup>

  <UsingTask Condition="'$(RunAOTCompilation)' == 'true'"
             TaskName="NdkToolFinderTask"
             AssemblyFile="$(MobileBuildTasksAssemblyPath)" />
  <UsingTask Condition="'$(AndroidGenerateAppBundle)' == 'true'"
             TaskName="AndroidAppBuilderTask"
             AssemblyFile="$(AndroidAppBuilderTasksAssemblyPath)" />

  <Target Name="AndroidBuild" AfterTargets="$(AndroidBuildAfterThisTarget)" />

  <Target Name="_AndroidCoreBuild" BeforeTargets="AndroidBuild" DependsOnTargets="$(AndroidBuildDependsOn)" />

  <Target Name="_InitializeCommonProperties">
    <Error Condition="'$(IntermediateOutputPath)' == ''" Text="%24(IntermediateOutputPath) property needs to be set" />

    <PropertyGroup>
      <_MobileIntermediateOutputPath>$([MSBuild]::NormalizeDirectory($(IntermediateOutputPath), 'mobile'))</_MobileIntermediateOutputPath>
      <TargetArchitecture Condition="'$(TargetArchitecture)' == ''">$(PlatformTarget)</TargetArchitecture>
    </PropertyGroup>

    <PropertyGroup>
      <MicrosoftNetCoreAppRuntimePackDir Condition="'$(MicrosoftNetCoreAppRuntimePackDir)' == ''">%(ResolvedRuntimePack.PackageDirectory)</MicrosoftNetCoreAppRuntimePackDir>
      <MicrosoftNetCoreAppRuntimePackRidDir Condition="'$(MicrosoftNetCoreAppRuntimePackRidDir)' == ''">$([MSBuild]::NormalizeDirectory($(MicrosoftNetCoreAppRuntimePackDir), 'runtimes', '$(TargetOS)-$(TargetArchitecture)'))</MicrosoftNetCoreAppRuntimePackRidDir>
      <MicrosoftNetCoreAppRuntimePackRidDir>$([MSBuild]::NormalizeDirectory($(MicrosoftNetCoreAppRuntimePackRidDir)))</MicrosoftNetCoreAppRuntimePackRidDir>
      <MicrosoftNetCoreAppRuntimePackRidNativeDir>$([MSBuild]::NormalizeDirectory($(MicrosoftNetCoreAppRuntimePackRidDir), 'native'))</MicrosoftNetCoreAppRuntimePackRidNativeDir>
    </PropertyGroup>

    <PropertyGroup>
      <AndroidBuildDir Condition="'$(AndroidBuildDir)' == ''">$([MSBuild]::NormalizeDirectory($(PublishDir)))</AndroidBuildDir>
      <AndroidBundleDir Condition="'$(AndroidBundleDir)' == ''">$([MSBuild]::NormalizeDirectory('$(OutDir)', 'Bundle'))</AndroidBundleDir>

      <BundleDir>$(AndroidBundleDir)</BundleDir>
      <_MonoHeaderPath>$([MSBuild]::NormalizeDirectory($(MicrosoftNetCoreAppRuntimePackRidNativeDir), 'include', 'mono-2.0'))</_MonoHeaderPath>
    </PropertyGroup>

    <ItemGroup Condition="'$(UseNativeAOTRuntime)' != 'true'">
      <RuntimeComponents Condition="'$(UseAllRuntimeComponents)' == 'true'" Include="@(_MonoRuntimeAvailableComponents)" />
      <!-- Make sure marshal-ilgen is included in the components list. -->
      <RuntimeComponents Condition="'$(UseAllRuntimeComponents)' != 'true'" Include="marshal-ilgen" KeepDuplicates="false" />
    </ItemGroup>

    <ItemGroup Condition="'$(_IsLibraryMode)' == 'true'">
      <_CommonLinkerArgs Include="-l:libz.so" />
      <_CommonLinkerArgs Include="-l:liblog.so" />
      <_CommonLinkerArgs Include="-l:libc.so" />
      <_CommonLinkerArgs Include="-l:libm.so" />
      <_CommonLinkerArgs Include="--build-id=sha1" />

      <!-- include all libraries except components -->
      <_RuntimeLibraries Include="$(AndroidBuildDir)\*.a" Exclude="$(AndroidBuildDir)\libmono-component-*.a" />
      <!-- include all component stub libraries -->
      <_RuntimeLibraries Include="$(AndroidBuildDir)\libmono-component-*-stub-static.a" />
      <!-- if RuntimeComponents is not empty, remove stubs for the required components and include the actual component library -->
      <_RuntimeLibraries Condition="'@(RuntimeComponents)' != ''" Remove="$(AndroidBuildDir)\libmono-component-%(RuntimeComponents.Identity)-stub-static.a" />
      <_RuntimeLibraries Condition="'@(RuntimeComponents)' != ''" Include="$(AndroidBuildDir)\libmono-component-%(RuntimeComponents.Identity)-static.a" />
      <!-- if RuntimeComponents is empty, do nothing as we already included all the component stubs above -->
    </ItemGroup>
  </Target>

  <Target Name="_BeforeAndroidBuild">
    <PropertyGroup>
      <_AndroidRuntimeConfigFilePath Condition="'$(_AndroidRuntimeConfigFilePath)' == ''">$([MSBuild]::NormalizePath($(AndroidBuildDir), '$(AssemblyName).runtimeconfig.json'))</_AndroidRuntimeConfigFilePath>
      <_ParsedRuntimeConfigFilePath Condition="'$(_ParsedRuntimeConfigFilePath)' == ''">$([MSBuild]::NormalizePath($(AndroidBuildDir), 'runtimeconfig.bin'))</_ParsedRuntimeConfigFilePath>
    </PropertyGroup>

    <RemoveDir Directories="$(AndroidBundleDir)" />
    <MakeDir Directories="$(AndroidBundleDir)" />
  </Target>

  <Target Name="_AndroidResolveReferences">
    <ItemGroup Condition="'$(EnableDefaultAssembliesToBundle)' == 'true'">
      <AndroidAssembliesToBundle Remove="@(AndroidAssembliesToBundle)" />
      <AndroidAssembliesToBundle Include="$(PublishDir)\**\*.dll" />
    </ItemGroup>

    <ItemGroup>
      <_AssembliesToBundleInternal Remove="@(_AssembliesToBundleInternal)" />
      <_AssembliesToBundleInternal Include="@(AndroidAssembliesToBundle)">
        <_InternalForceInterpret>%(AndroidAssembliesToBundle._InternalForceInterpret)</_InternalForceInterpret>
        <_IsNative>%(AndroidAssembliesToBundle._IsNative)</_IsNative>
      </_AssembliesToBundleInternal>
    </ItemGroup>
  </Target>

  <Target Name="_AndroidBeforeAotCompile">
    <PropertyGroup>
      <_AOTMode Condition="'$(UseMonoJustInterp)' != 'true'">Normal</_AOTMode>
      <_AOTMode Condition="'$(UseMonoJustInterp)' == 'true'">JustInterp</_AOTMode>
      <_AOTMode Condition="'$(ForceFullAOT)' == 'true'">Full</_AOTMode>
      <_AotOutputType>AsmOnly</_AotOutputType>
    </PropertyGroup>
    <!-- Should consider renaming property to something more appropriate-->
    <PropertyGroup Condition="'$(AOTWithLibraryFiles)' == 'true'">
      <_AotOutputType>Library</_AotOutputType>
      <_AotLibraryFormat>So</_AotLibraryFormat>
    </PropertyGroup>
    <PropertyGroup Condition="'$(AOTWithLibraryFiles)' != 'true'">
      <_AotModuleTablePath>$(AndroidBundleDir)\modules.c</_AotModuleTablePath>
    </PropertyGroup>

    <PropertyGroup Condition="'$(_IsLibraryMode)' == 'true'">
      <_UsesRuntimeInitCallback>$(UsesRuntimeInitCallback)</_UsesRuntimeInitCallback>
      <_UsesRuntimeInitCallback Condition="'$(_UsesRuntimeInitCallback)' == ''">true</_UsesRuntimeInitCallback>
      <_AotOutputType>ObjectFile</_AotOutputType>
    </PropertyGroup>

    <ItemGroup>
      <MonoAOTCompilerDefaultAotArguments Condition="'$(TargetArchitecture)' == 'arm'" Include="mtriple=armv7-linux-gnueabi" />
      <MonoAOTCompilerDefaultAotArguments Condition="'$(TargetArchitecture)' == 'arm64'" Include="mtriple=aarch64-linux-android" />
      <MonoAOTCompilerDefaultAotArguments Condition="'$(TargetArchitecture)' == 'x86'" Include="mtriple=i686-linux-android" />
      <MonoAOTCompilerDefaultAotArguments Condition="'$(TargetArchitecture)' == 'x64'" Include="mtriple=x86_64-linux-android" />

      <MonoAOTCompilerDefaultAotArguments Include="static" />
      <MonoAOTCompilerDefaultAotArguments Include="dwarfdebug" />
      <MonoAOTCompilerDefaultAotArguments Condition="'$(_IsLibraryMode)' == 'true'" Include="direct-icalls" />
      <MonoAOTCompilerDefaultAotArguments Condition="'$(_UsesRuntimeInitCallback)' == 'true' and $(CustomRuntimeInitCallback) == ''" Include="runtime-init-callback" />
      <MonoAOTCompilerDefaultAotArguments Condition="'$(_UsesRuntimeInitCallback)' == 'true' and $(CustomRuntimeInitCallback) != ''" Include="runtime-init-callback=$(CustomRuntimeInitCallback)" />

      <MonoAOTCompilerDefaultAotArguments Include="nimt-trampolines=2000" />
      <MonoAOTCompilerDefaultAotArguments Include="ntrampolines=10000" />
      <MonoAOTCompilerDefaultAotArguments Include="nrgctx-fetch-trampolines=256" />
      <MonoAOTCompilerDefaultAotArguments Include="ngsharedvt-trampolines=4400" />
      <MonoAOTCompilerDefaultAotArguments Include="nftnptr-arg-trampolines=4000" />
      <MonoAOTCompilerDefaultAotArguments Include="nrgctx-trampolines=31000" />
    </ItemGroup>

    <PropertyGroup>
      <AotArguments>@(MonoAOTCompilerDefaultAotArguments, ';')</AotArguments>
      <ProcessArguments>@(MonoAOTCompilerDefaultProcessArguments, ';')</ProcessArguments>
    </PropertyGroup>

    <PropertyGroup>
      <AndroidLibraryMinApiLevel Condition="'$(AndroidLibraryMinApiLevel)' == ''">21</AndroidLibraryMinApiLevel>
    </PropertyGroup>

    <NdkToolFinderTask
      Condition="'$(AOTWithLibraryFiles)' == 'true' or '$(_IsLibraryMode)' == 'true'"
      Architecture="$(TargetArchitecture)"
      HostOS="$(_HostOS)"
      MinApiLevel="$(AndroidLibraryMinApiLevel)">
      <Output TaskParameter="AsPrefixPath" PropertyName="_AsPrefixPath" />
      <Output TaskParameter="ToolPrefixPath" PropertyName="_ToolPrefixPath" />
      <Output TaskParameter="Triple" PropertyName="_Triple" />
      <Output TaskParameter="LdName" PropertyName="_LdName" />
      <Output TaskParameter="LdPath" PropertyName="_LdPath" />
      <Output TaskParameter="ClangPath" PropertyName="_ClangPath" />
    </NdkToolFinderTask>

    <PropertyGroup Condition="'$(AOTWithLibraryFiles)' == 'true' or '$(_IsLibraryMode)' == 'true'">
      <_AsPrefixPath>$([MSBuild]::EnsureTrailingSlash('$(_AsPrefixPath)'))</_AsPrefixPath>
      <_ToolPrefixPath>$([MSBuild]::EnsureTrailingSlash('$(_ToolPrefixPath)'))</_ToolPrefixPath>
    </PropertyGroup>

    <ItemGroup>
      <_AotInputAssemblies Include="@(_AssembliesToBundleInternal)"
                           Condition="'%(_AssembliesToBundleInternal._InternalForceInterpret)' != 'true'">
        <AotArguments>$(AotArguments)</AotArguments>
        <ProcessArguments>$(ProcessArguments)</ProcessArguments>
      </_AotInputAssemblies>

      <_AOT_InternalForceInterpretAssemblies Include="@(_AssembliesToBundleInternal->WithMetadataValue('_InternalForceInterpret', 'true'))" />
      <_AssembliesToBundleInternal Remove="@(_AssembliesToBundleInternal)" />
    </ItemGroup>

    <MakeDir Directories="$(_MobileIntermediateOutputPath)" />
  </Target>

  <Target Name="_AndroidPrepareProfiledAot"
          Condition="'$(NetTraceFilePath)' != '' and '$(ForceFullAOT)' != 'true'"
          DependsOnTargets="_AndroidBeforeAotCompile">
    <PropertyGroup>
      <_ToolPath>$([System.IO.Path]::GetDirectoryName('$(DotnetPgoToolPath)'))</_ToolPath>
    </PropertyGroup>

    <NetTraceToMibcConverter
      ToolPath="$(_ToolPath)"
      Assemblies="@(_AotInputAssemblies)"
      NetTraceFilePath="$(NetTraceFilePath)"
      OutputDir="$(_MobileIntermediateOutputPath)">
      <Output TaskParameter="MibcFilePath" ItemName="ProfiledAOTProfilePaths" />
    </NetTraceToMibcConverter>
  </Target>

  <Target Name="_AndroidAotCompile"
          Condition="'$(RunAOTCompilation)' == 'true'"
          DependsOnTargets="_AndroidBeforeAotCompile">

    <PropertyGroup Condition="'$(_IsLibraryMode)' == 'true'">
      <_EnableUnmanagedCallersOnlyMethodsExport>true</_EnableUnmanagedCallersOnlyMethodsExport>
      <_UseAotDataFile>$(UseAotDataFile)</_UseAotDataFile>
      <_UseAotDataFile Condition="'$(_UseAotDataFile)' == ''">false</_UseAotDataFile>
    </PropertyGroup>

    <ItemGroup>
      <ProfiledAOTProfilePaths Include="$(MibcFilePath)" />
    </ItemGroup>

    <!-- 
      In order for the runtime to work when static linking, we must supply 
      a list of direct pinvokes otherwise the runtime will crash
    -->
    <ItemGroup Condition="'$(_IsLibraryMode)' == 'true'">
      <DirectPInvokes Include="libSystem.Native" />
      <DirectPInvokes Include="libSystem.IO.Compression.Native" />
      <DirectPInvokes Include="libSystem.Security.Cryptography.Native.Android" />
    </ItemGroup>

    <PropertyGroup>
      <_CompilerBinaryPath>@(MonoAotCrossCompiler->WithMetadataValue('RuntimeIdentifier','$(TargetOS.ToLowerInvariant())-$(TargetArchitecture.ToLowerInvariant())'))</_CompilerBinaryPath>
      <_MonoLLVMPath>$(MonoAotCrossDir)</_MonoLLVMPath>
      <_MonoLLVMPath Condition="'$(_MonoLLVMPath)' == '' and '$(MonoEnableLLVM)' == 'true'">$([System.IO.Path]::GetDirectoryName("$(_CompilerBinaryPath)"))</_MonoLLVMPath>
    </PropertyGroup>

    <MonoAOTCompiler
        AotModulesTablePath="$(_AotModuleTablePath)"
        AsPrefix="$(_AsPrefixPath)"
        Assemblies="@(_AotInputAssemblies)"
        CompilerBinaryPath="$(_CompilerBinaryPath)"
        DirectPInvokes="@(DirectPInvokes)"
        DirectPInvokeLists="@(DirectPInvokeLists)"
        EnableUnmanagedCallersOnlyMethodsExport="$(_EnableUnmanagedCallersOnlyMethodsExport)"
        IntermediateOutputPath="$(_MobileIntermediateOutputPath)"
        LibraryFormat="$(_AotLibraryFormat)"
        LLVMPath="$(_MonoLLVMPath)"
        MibcProfilePath="@(ProfiledAOTProfilePaths)"
        Mode="$(_AOTMode)"
        OutputDir="$(_MobileIntermediateOutputPath)"
        OutputType="$(_AotOutputType)"
        ToolPrefix="$(_ToolPrefixPath)"
        UseAotDataFile="$(_UseAotDataFile)"
        UseLLVM="$(MonoEnableLLVM)">
        <Output TaskParameter="CompiledAssemblies" ItemName="_AssembliesToBundleInternal" />
    </MonoAOTCompiler>

    <ItemGroup>
      <_AssembliesToBundleInternal Include="@(_AOT_InternalForceInterpretAssemblies)" />
    </ItemGroup>
  </Target>


  <Target
    Name="_AndroidGenerateAppBundle"
    Condition="$(AndroidGenerateAppBundle) == 'true'"
    DependsOnTargets="_AndroidGenerateRuntimeConfig">

    <ItemGroup Condition="'$(_IsLibraryMode)' == 'true'">
      <_NativeDependencies Include="$(LibraryOutputPath)" />
    </ItemGroup>

    <AndroidAppBuilderTask
        AppDir="$(AndroidBuildDir)"
        Assemblies="@(_AssembliesToBundleInternal)"
        DiagnosticPorts="$(DiagnosticPorts)"
        EnvironmentVariables="@(AndroidEnv)"
        ExtraLinkerArguments="@(ExtraAppLinkerArgs)"
        ForceAOT="$(RunAOTCompilation)"
        ForceFullAOT="$(ForceFullAOT)"
        ForceInterpreter="$(MonoForceInterpreter)"
        IsLibraryMode="$(_IsLibraryMode)"
        MainLibraryFileName="$(MainLibraryFileName)"
        MonoRuntimeHeaders="$(_MonoHeaderPath)"
        NativeDependencies="@(_NativeDependencies)"
        OutputDir="$(AndroidBundleDir)"
        ProjectName="$(AssemblyName)"
        RuntimeComponents="@(RuntimeComponents)"
        RuntimeIdentifier="$(RuntimeIdentifier)"
        StripDebugSymbols="False">
        <Output TaskParameter="ApkBundlePath" PropertyName="ApkBundlePath" />
        <Output TaskParameter="ApkPackageId"  PropertyName="ApkPackageId" />
    </AndroidAppBuilderTask>

    <Message Importance="High" Text="PackageId:       $(ApkPackageId)"/>
    <Message Importance="High" Text="Instrumentation: net.dot.MonoRunner"/>
    <Message Importance="High" Text="Apk:             $(ApkBundlePath)"/>
  </Target>

  <Target Name="_AfterAndroidBuild">

  </Target>

  <Target Name="_AndroidGenerateRuntimeConfig"
          Inputs="$(_AndroidRuntimeConfigFilePath)"
          Outputs="$(_ParsedRuntimeConfigFilePath)"
          Condition="Exists('$(_AndroidRuntimeConfigFilePath)')"
          BeforeTargets="_GenerateBundle">
    <ItemGroup>
      <_RuntimeConfigReservedProperties Include="RUNTIME_IDENTIFIER"/>
      <_RuntimeConfigReservedProperties Include="APP_CONTEXT_BASE_DIRECTORY"/>
    </ItemGroup>

    <RuntimeConfigParserTask
        RuntimeConfigFile="$(_AndroidRuntimeConfigFilePath)"
        OutputFile="$(_ParsedRuntimeConfigFilePath)"
        RuntimeConfigReservedProperties="@(_RuntimeConfigReservedProperties)">
    </RuntimeConfigParserTask>
  </Target>
</Project>
